package com.restkeeper.store.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.beust.jcommander.internal.Lists;
import com.restkeeper.exception.BussinessException;
import com.restkeeper.print.PrintContent;
import com.restkeeper.print.PrintOrder;
import com.restkeeper.print.PrinterRow;
import com.restkeeper.print.PrinterTable;
import com.restkeeper.store.entity.Dish;
import com.restkeeper.store.entity.Printer;
import com.restkeeper.store.entity.PrinterDish;
import com.restkeeper.store.mapper.PrinterDishMapper;
import com.restkeeper.store.mapper.PrinterMapper;
import com.restkeeper.tenant.TenantContext;
import com.restkeeper.utils.SystemCode;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Component
@Service(version = "1.0.0",protocol = "dubbo")
public class PrinterServiceImpl extends ServiceImpl<PrinterMapper, Printer> implements IPrinterService{
//    @Autowired
//    private PrinterConfig printerConfig;
    @Reference(version = "1.0.0", check=false)
    private IDishService dishService;
//    @Reference(version = "1.0.0", check=false)
//    private IOrderService orderService;
//    @Reference(version = "1.0.0", check=false)
//    private IOrderDetailService orderDetailService;

    @Autowired
    private PrinterDishMapper printerDishMapper;

    @Override
    public void frontPrint(PrintOrder printOrder, int printType,String storeId,String shopId) {
        TenantContext.addAttachment("storeId",storeId);
        TenantContext.addAttachment("shopId",shopId);
        PrintContent printContent = new PrintContent();
        if(printType == SystemCode.PRINT_BEFOREHAND){
            printContent.setTitle("预结单");
        }else if(printType == SystemCode.PRINT_BILL){
            printContent.setTitle("结账单");
        }else if(printType == SystemCode.PRINT_CUSTOMER){
            printContent.setTitle("客单");
        }
        QueryWrapper<Printer> printerQueryWrapper = new QueryWrapper<>();
        printerQueryWrapper.lambda()
                .eq(Printer::getAreaType,2);
        Printer printer = this.getOne(printerQueryWrapper);
        printContent.setCopies(printer.getPrinterNumber());

        //OrderEntity orderEntity = orderService.getById(orderId);
        printContent.setSerialNumber("流水号："+printOrder.getOrderNumber());
        List<String> streamContent = Lists.newArrayList();
        streamContent.add("人数："+printOrder.getPersonNumber());
        streamContent.add("账单号："+printOrder.getOrderId());
        streamContent.add("开台时间："+ printOrder.getCreateTime());
        //streamContent.add("开台时间："+orderEntity.getCreateTime().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        if(printType == SystemCode.PRINT_BILL){
            //streamContent.add("结账时间："+orderEntity.getLastUpdateTime().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
            streamContent.add("结账时间：" + printOrder.getBillTime());
        }
        printContent.setStreamContent(streamContent);
        PrinterTable printerTable = new PrinterTable();
        PrinterRow row = new PrinterRow();
        row.addColumn("品名");
        row.addColumn("单价");
        row.addColumn("数量");
        row.addColumn("总额");
        printerTable.addRow(row);
        AtomicInteger totalPrice = new AtomicInteger();
        printOrder.getDishList().forEach(d->{
            PrinterRow printerRow = new PrinterRow();
            printerRow.addColumn(d.getDishName());
            totalPrice.set(totalPrice.get() + d.getPrice());
            float price = ((float) d.getPrice())/100;
            printerRow.addColumn(price+"");
            printerRow.addColumn(d.getDishNumber()+"");
            float amount = ((float)d.getAmount())/100;
            printerRow.addColumn(amount + "");
            printerTable.addRow(printerRow);
        });
        printContent.setPrinterTable(printerTable);
        List<String> simpleContent = Lists.newArrayList();
        simpleContent.add("原价合计："+((float)totalPrice.get())/100);
        printContent.setPrintSimpleContent(simpleContent);
        if(printType == SystemCode.PRINT_BILL){
            printContent.setPrintBottom("实收金额："+((float)printOrder.getPayAmount()/100));
        }
        //print(printContent,printer.getMachineCode());
    }

    @Override
    public void backendPrint(String dishId,int printType,int dishNumber,String storeId,String shopId) {
        TenantContext.addAttachment("storeId",storeId);
        TenantContext.addAttachment("shopId",shopId);
        QueryWrapper<PrinterDish> qw = new QueryWrapper<>();
        qw.lambda()
                .eq(PrinterDish::getDishId,dishId);
        PrinterDish printerDish = printerDishMapper.selectOne(qw);
        if(printerDish == null) return;
        Dish dish = dishService.getById(dishId);
        PrintContent printContent = new PrintContent();
        if(printType == SystemCode.PRINT_MADE_MENU){
            printContent.setTitle("制作菜单");
        }else if(printType == SystemCode.PRINT_RETURN_DISH){
            printContent.setTitle("退菜单");
        }else if(printType == SystemCode.PRINT_CHANGE_MENU){
            printContent.setTitle("转菜单");
        }else if(printType == SystemCode.PRINT_CHANGE_TABLE){
            printContent.setTitle("转台单");
        }
        List<String> contents = Lists.newArrayList();
        contents.add(dish.getName() + " " + dishNumber+"份");
        printContent.setStreamContent(contents);

        Printer printer = this.getById(printerDish.getPrinterId());
        String machineCode = printer.getMachineCode();
        printContent.setCopies(printer.getPrinterNumber());

    }

    @Override
    public boolean addFrontPrinter(Printer printer) {
        return this.save(printer);
    }

    @Override
    @Transactional
    public boolean addBackendPrinter(Printer printer, List<String> dishIdList) {
        this.save(printer);
        dishIdList.forEach(d->{
            PrinterDish printerDish = new PrinterDish();
            printerDish.setPrinterId(printer.getPrinterId());
            printerDish.setDishId(d);
            printerDishMapper.insert(printerDish);
        });

        return true;
    }

    @Override
    @Transactional
    public boolean updatePrinter(Printer printer,List<String> dishIdList){
        this.updateById(printer);
        if(printer.getAreaType() != 1) return true;

        if(dishIdList == null) throw new BussinessException("请给后厨打印机关联菜品！");
        UpdateWrapper<PrinterDish> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda()
                .eq(PrinterDish::getPrinterId,printer.getPrinterId());
        printerDishMapper.delete(updateWrapper);
        dishIdList.forEach(d->{
            PrinterDish printerDish = new PrinterDish();
            printerDish.setPrinterId(printer.getPrinterId());
            printerDish.setDishId(d);
            printerDishMapper.insert(printerDish);
        });

        return true;
    }

    @Override
    public IPage<Printer> queryPage(Long pageNo, Long pageSize) {
        QueryWrapper<Printer> qw = new QueryWrapper<>();
        qw.lambda()
                .orderByDesc(Printer::getLastUpdateTime);
        Page<Printer> page = new Page<>(pageNo,pageSize);

        this.page(page,qw);

        for (Printer priner:page.getRecords()) {
            QueryWrapper<PrinterDish> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(PrinterDish::getPrinterId,priner.getPrinterId());
            priner.setDishIdList(printerDishMapper.selectList(wrapper).stream().map(pd->pd.getDishId()).collect(Collectors.toList()));
        }

        return page;
    }


}
